package com.durian.base.rxhttp

import android.content.Context
import com.durian.base.rxhttp.cache.CacheManager
import com.durian.base.rxhttp.cache.CacheMode
import com.durian.base.rxhttp.cache.CacheStrategy
import com.durian.base.rxhttp.logging.LoggingInterceptor
import com.durian.base.rxhttp.param.IParam
import com.durian.base.rxhttp.param.RxBaseParam
import com.durian.base.rxhttp.param.RxNobodyParam
import com.durian.base.rxhttp.param.RxPostParam
import com.durian.base.rxhttp.ssl.SSLSocketFactoryImpl
import com.durian.base.rxhttp.ssl.X509TrustManagerImpl
import com.durian.base.utils.FileUtils
import okhttp3.Call
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.File
import java.util.concurrent.TimeUnit
import javax.net.ssl.HostnameVerifier


/**
 * 说明：HttpSender
 * <p/>
 * 作者：Fanly
 * <p/>
 * 类型：Class
 * <p/>
 * 时间：2020/04/23 18:24
 * <p/>
 * 版本：version 1.0
 */
object RxHttp {

    private var _okHttpClient: OkHttpClient? = null
    private var _debug = false
    private var _paramAssembly: ((IParam<*>) -> Unit)? = null
    private var _error: ((Throwable) -> Unit)? = null
    private var _defalutClientConfig: ((OkHttpClient.Builder) -> Unit)? = null
    private var _cacheManager: CacheManager? = null
    private var _cacheStrategy = CacheStrategy(CacheMode.ONLY_NETWORK, -1, "")
    private var _requestBodyHook: ((IParam<*>, Map<String, String>) -> Unit)? = null
    private val _cacheFileName = "RxHttp0527"
    private var _cacheFile : File? = null

//    init config

    fun setRequestBodyHook(_hook: ((IParam<*>, Map<String, String>) -> Unit)?): RxHttp {
        _requestBodyHook = _hook
        return this;
    }

    fun getRequestBodyHook() : ((IParam<*>, Map<String, String>) -> Unit)?{
        return _requestBodyHook
    }

    /**
     * 清空缓存
     */
    suspend fun cleanCache(){
        if (_cacheFile?.isDirectory == true && _cacheFile?.exists() == true){
            FileUtils.deleteAllFile(_cacheFile)
        }
    }

    /**
     * 设置缓存策略
     * @param maxSize 默认10M
     */
    fun setCache(context: Context,maxSize: Long = 10 * 1024 * 1024): RxHttp {
        return setCache(File(context.externalCacheDir, _cacheFileName), maxSize)
    }

    fun setCache(directory: File, maxSize: Long = 10 * 1024 * 1024): RxHttp {
        _cacheManager = CacheManager(directory, maxSize)
        _cacheFile = directory
        return this
    }

    fun setCacheStrategy(cacheStrategy: CacheStrategy): RxHttp {
        _cacheStrategy = cacheStrategy
        return this
    }

    fun getCacheStrategy(): CacheStrategy {
        return _cacheStrategy.copy()
    }

    fun getCacheManager(): CacheManager? {
        return _cacheManager
    }

    /**
     * 调试模式
     */
    fun setDebug(debug: Boolean): RxHttp {
        _debug = debug
        return this
    }

    fun isDebug(): Boolean {
        return _debug
    }

    /**
     * 设置okhttp客户端
     */
    @Synchronized
    fun setOkHttpClient(client: OkHttpClient): RxHttp {
        _okHttpClient = client
        return this
    }

    fun setDefaultClientConfig(config: (OkHttpClient.Builder) -> Unit): RxHttp {
        _defalutClientConfig = config
        return this;
    }

    fun getDefaultClientConfig(): ((OkHttpClient.Builder) -> Unit)? {
        return _defalutClientConfig
    }

    private fun getDefaultOkHttpClientBuilder(): OkHttpClient.Builder {
        val trustAllCert = X509TrustManagerImpl()
        val sslSocketFactory = SSLSocketFactoryImpl(trustAllCert)
        val builder = OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .sslSocketFactory(sslSocketFactory, trustAllCert)//添加信任证书
                .hostnameVerifier(HostnameVerifier { _, _ -> true })//忽略host验证
        if (isDebug()) {
            builder.addInterceptor(LoggingInterceptor(tag = "RxHttp"))
        }
        getDefaultClientConfig()?.invoke(builder)
        return builder
    }

    @Synchronized
    @JvmStatic
    fun getOkHttpClient(): OkHttpClient {
        if (_okHttpClient == null){
            _okHttpClient = getDefaultOkHttpClientBuilder().build()
        }
        return _okHttpClient!!
    }

    /**
     * 设置错误处理器
     */
    fun setErrorHandler(error: (Throwable) -> Unit): RxHttp {
        _error = error
        return this
    }

    fun getErrorHandler(): ((Throwable) -> Unit)? {
        return _error
    }

    /**
     * 设置公共参数
     */
    fun setParamAssembly(params: (IParam<*>) -> Unit): RxHttp {
        _paramAssembly = params
        return this
    }

    fun getParamAssembly(): ((IParam<*>) -> Unit)? {
        return _paramAssembly
    }

    fun getHttpUrl(url: String): String {
        return if (url.isNotEmpty() && url.toLowerCase().startsWith("http")) {
            url
        }else{
            "https://${url}"
        }
    }


//    http method

    fun post(url: String): RxPostParam {
        return RxBaseParam.post(url)
    }

    fun head(url: String): RxNobodyParam {
        return RxBaseParam.head(url)
    }

    fun get(url: String): RxNobodyParam {
        return RxBaseParam.get(url)
    }

    fun put(url: String): RxPostParam {
        return RxBaseParam.put(url)
    }

    fun patch(url: String): RxPostParam {
        return RxBaseParam.patch(url)
    }

    fun delete(url: String): RxPostParam {
        return RxBaseParam.delete(url)
    }

    fun newCall(client: OkHttpClient, request: Request): Call {
        return client.newCall(request)
    }

    /**
     * 取消所有请求
     */
    fun cancelAll() {
        CallCancelFactory.cancelAll()
    }

    /**
     * 取消请求
     */
    fun cancelTag(tag: String) {
        CallCancelFactory.cancelCall(tag)
    }

}